{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Prompt Templates and Variables Tutorial (Using Jinja2)\n",
    "\n",
    "## Overview\n",
    "\n",
    "This tutorial provides a comprehensive introduction to creating and using prompt templates with variables in the context of AI language models. It focuses on leveraging Python and the Jinja2 templating engine to create flexible, reusable prompt structures that can incorporate dynamic content. The tutorial demonstrates how to interact with OpenAI's GPT models using these advanced prompting techniques.\n",
    "\n",
    "## Motivation\n",
    "\n",
    "As AI language models become increasingly sophisticated, the ability to craft effective prompts becomes crucial for obtaining desired outputs. Prompt templates and variables offer several advantages:\n",
    "\n",
    "1. **Reusability**: Templates can be reused across different contexts, saving time and ensuring consistency.\n",
    "2. **Flexibility**: Variables allow for dynamic content insertion, making prompts adaptable to various scenarios.\n",
    "3. **Complexity Management**: Templates can handle complex structures, including conditional logic and loops, enabling more sophisticated interactions with AI models.\n",
    "4. **Scalability**: As applications grow, well-structured templates make it easier to manage and maintain large numbers of prompts.\n",
    "\n",
    "This tutorial aims to equip learners with the knowledge and skills to create powerful, flexible prompt templates, enhancing their ability to work effectively with AI language models.\n",
    "\n",
    "## Key Components\n",
    "\n",
    "The tutorial covers several key components:\n",
    "\n",
    "1. **PromptTemplate Class**: A custom class that wraps Jinja2's Template class, providing a simple interface for creating and using templates.\n",
    "2. **Jinja2 Templating**: Utilization of Jinja2 for advanced templating features, including variable insertion, conditional statements, and loops.\n",
    "3. **OpenAI API Integration**: Direct use of the OpenAI API for sending prompts and receiving responses from GPT models.\n",
    "4. **Variable Handling**: Techniques for incorporating variables into templates and managing dynamic content.\n",
    "5. **Conditional Logic**: Implementation of if-else statements within templates to create context-aware prompts.\n",
    "6. **Advanced Formatting**: Methods for structuring complex prompts, including list formatting and multi-part instructions.\n",
    "\n",
    "## Method Details\n",
    "\n",
    "The tutorial employs a step-by-step approach to introduce and demonstrate prompt templating concepts:\n",
    "\n",
    "1. **Setup and Environment**: The lesson begins by setting up the necessary libraries, including Jinja2 and the OpenAI API client.\n",
    "\n",
    "2. **Basic Template Creation**: Introduction to creating simple templates with single and multiple variables using the custom PromptTemplate class.\n",
    "\n",
    "3. **Variable Insertion**: Demonstration of how to insert variables into templates using Jinja2's `{{ variable }}` syntax.\n",
    "\n",
    "4. **Conditional Content**: Exploration of using if-else statements in templates to create prompts that adapt based on provided variables.\n",
    "\n",
    "5. **List Processing**: Techniques for handling lists of items within templates, including iteration and formatting.\n",
    "\n",
    "6. **Advanced Templating**: Demonstration of more complex template structures, including nested conditions, loops, and multi-part prompts.\n",
    "\n",
    "7. **Dynamic Instruction Generation**: Creation of templates that can generate structured instructions based on multiple input variables.\n",
    "\n",
    "8. **API Integration**: Throughout the tutorial, examples show how to use the templates with the OpenAI API to generate responses from GPT models.\n",
    "\n",
    "The methods are presented with practical examples, progressing from simple to more complex use cases. Each concept is explained theoretically and then demonstrated with a practical application.\n",
    "\n",
    "## Conclusion\n",
    "\n",
    "This tutorial provides a solid foundation in creating and using prompt templates with variables, leveraging the power of Jinja2 for advanced templating features. By the end of the lesson, learners will have gained:\n",
    "\n",
    "1. Understanding of the importance and applications of prompt templates in AI interactions.\n",
    "2. Practical skills in creating reusable, flexible prompt templates.\n",
    "3. Knowledge of how to incorporate variables and conditional logic into prompts.\n",
    "4. Experience in structuring complex prompts for various use cases.\n",
    "5. Insight into integrating templated prompts with the OpenAI API.\n",
    "\n",
    "These skills enable more sophisticated and efficient interactions with AI language models, opening up possibilities for creating more advanced, context-aware AI applications. The techniques learned can be applied to a wide range of scenarios, from simple query systems to complex, multi-turn conversational agents."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import openai\n",
    "from jinja2 import Template\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "openai.api_key = os.getenv('OPENAI_API_KEY')\n",
    "\n",
    "def get_completion(prompt, model=\"gpt-4o-mini\"):\n",
    "    ''' Get a completion from the OpenAI API \n",
    "    Args:\n",
    "        prompt (str): The prompt to send to the API\n",
    "        model (str): The model to use for the completion\n",
    "    Returns:\n",
    "        str: The completion text\n",
    "    '''\n",
    "    messages = [{\"role\": \"user\", \"content\": prompt}]\n",
    "    response = openai.ChatCompletion.create(\n",
    "        model=model,\n",
    "        messages=messages,\n",
    "        temperature=0,\n",
    "    )\n",
    "    return response.choices[0].message[\"content\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Creating Reusable Prompt Templates\n",
    "\n",
    "We'll create a PromptTemplate class that uses Jinja2 for templating:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Simple Template Result:\n",
      "Photosynthesis is the process by which green plants, algae, and some bacteria convert light energy, usually from the sun, into chemical energy stored in glucose. This process primarily occurs in the chloroplasts of plant cells, where chlorophyll, the green pigment, captures light energy. \n",
      "\n",
      "During photosynthesis, carbon dioxide (CO₂) from the atmosphere and water (H₂O) from the soil are used to produce glucose (C₆H₁₂O₆) and oxygen (O₂). The overall chemical equation for photosynthesis can be summarized as:\n",
      "\n",
      "6 CO₂ + 6 H₂O + light energy → C₆H₁₂O₆ + 6 O₂\n",
      "\n",
      "Photosynthesis is crucial for life on Earth, as it provides the oxygen we breathe and serves as the foundation of the food chain by producing organic compounds that serve as energy sources for other organisms.\n",
      "\n",
      "--------------------------------------------------\n",
      "\n",
      "Complex Template Result:\n",
      "Neural networks are a key technology in artificial intelligence that mimic the way the human brain works to process information. They consist of layers of interconnected nodes, or \"neurons,\" which work together to recognize patterns and make decisions.\n",
      "\n",
      "Here's a simple breakdown:\n",
      "\n",
      "1. **Structure**: A neural network has an input layer (where data enters), one or more hidden layers (where processing happens), and an output layer (where results come out).\n",
      "\n",
      "2. **Learning**: Neural networks learn from data by adjusting the connections (weights) between neurons based on the errors they make. This process is called training.\n",
      "\n",
      "3. **Function**: Once trained, neural networks can perform tasks like image recognition, language translation, and even playing games by predicting outcomes based on new input data.\n",
      "\n",
      "In essence, neural networks are powerful tools that help computers learn from experience, similar to how humans learn from their surroundings.\n"
     ]
    }
   ],
   "source": [
    "class PromptTemplate:\n",
    "    ''' A class to represent a template for generating prompts with variables\n",
    "    Attributes:\n",
    "        template (str): The template string with variables\n",
    "        input_variables (list): A list of the variable names in the template\n",
    "    '''\n",
    "    def __init__(self, template, input_variables):\n",
    "        self.template = Template(template)\n",
    "        self.input_variables = input_variables\n",
    "    \n",
    "    def format(self, **kwargs):\n",
    "        return self.template.render(**kwargs)\n",
    "\n",
    "# Simple template with one variable\n",
    "simple_template = PromptTemplate(\n",
    "    template=\"Provide a brief explanation of {{ topic }}.\",\n",
    "    input_variables=[\"topic\"]\n",
    ")\n",
    "\n",
    "# More complex template with multiple variables\n",
    "complex_template = PromptTemplate(\n",
    "    template=\"Explain the concept of {{ concept }} in the field of {{ field }} to a {{ audience }} audience, conciesly.\",\n",
    "    input_variables=[\"concept\", \"field\", \"audience\"]\n",
    ")\n",
    "\n",
    "# Using the simple template\n",
    "print(\"Simple Template Result:\")\n",
    "prompt = simple_template.format(topic=\"photosynthesis\")\n",
    "print(get_completion(prompt))\n",
    "\n",
    "print(\"\\n\" + \"-\"*50 + \"\\n\")\n",
    "\n",
    "# Using the complex template\n",
    "print(\"Complex Template Result:\")\n",
    "prompt = complex_template.format(\n",
    "    concept=\"neural networks\",\n",
    "    field=\"artificial intelligence\",\n",
    "    audience=\"beginner\"\n",
    ")\n",
    "print(get_completion(prompt))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Using Variables for Dynamic Content\n",
    "\n",
    "Now let's explore more advanced uses of variables, including conditional content:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Conditional Template Result (with profession):\n",
      "Sure, Alex! Here are some career tips for you as a software developer:\n",
      "\n",
      "1. **Continuous Learning**: Stay updated with the latest technologies and programming languages. Consider online courses or certifications in areas like cloud computing, AI, or cybersecurity.\n",
      "\n",
      "2. **Networking**: Attend industry meetups, conferences, and online forums to connect with other professionals. This can lead to job opportunities and collaborations.\n",
      "\n",
      "3. **Build a Portfolio**: Work on personal or open-source projects to showcase your skills. A strong portfolio can set you apart in job applications.\n",
      "\n",
      "4. **Soft Skills**: Develop communication and teamwork skills. Being able to collaborate effectively is crucial in software development.\n",
      "\n",
      "5. **Explore Specializations**: Consider specializing in a niche area (e.g., mobile development, data science, or DevOps) to enhance your marketability.\n",
      "\n",
      "6. **Seek Feedback**: Regularly ask for feedback from peers and mentors to improve your coding and problem-solving skills.\n",
      "\n",
      "7. **Work-Life Balance**: Prioritize your well-being to avoid burnout. A balanced life can enhance your productivity and creativity.\n",
      "\n",
      "Good luck with your career!\n",
      "\n",
      "Conditional Template Result (without profession):\n",
      "Sure, Sam! Here are some steps you can take:\n",
      "\n",
      "1. **Self-Assessment**: Identify your skills, interests, and values. Consider what you enjoy doing and what you're good at.\n",
      "\n",
      "2. **Explore Options**: Research different career paths that align with your interests. Look into industries that are growing and have job opportunities.\n",
      "\n",
      "3. **Education & Training**: Consider further education or certifications that can enhance your skills. Online courses can be a flexible option.\n",
      "\n",
      "4. **Networking**: Connect with professionals in your fields of interest through LinkedIn, local meetups, or industry events. Informational interviews can provide valuable insights.\n",
      "\n",
      "5. **Internships/Volunteering**: Gain experience through internships or volunteer work. This can help you build your resume and make connections.\n",
      "\n",
      "6. **Job Search**: Start applying for entry-level positions or roles that interest you. Tailor your resume and cover letter for each application.\n",
      "\n",
      "7. **Stay Positive**: Job searching can be challenging, but stay persistent and open to opportunities.\n",
      "\n",
      "Good luck!\n",
      "\n",
      "--------------------------------------------------\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Template with conditional content\n",
    "conditional_template = PromptTemplate(\n",
    "    template=\"My name is {{ name }} and I am {{ age }} years old. \"\n",
    "              \"{% if profession %}I work as a {{ profession }}.{% else %}I am currently not employed.{% endif %} \"\n",
    "              \"Can you give me career advice based on this information? answer concisely.\",\n",
    "    input_variables=[\"name\", \"age\", \"profession\"]\n",
    ")\n",
    "\n",
    "# Using the conditional template\n",
    "print(\"Conditional Template Result (with profession):\")\n",
    "prompt = conditional_template.format(\n",
    "    name=\"Alex\",\n",
    "    age=\"28\",\n",
    "    profession=\"software developer\"\n",
    ")\n",
    "print(get_completion(prompt))\n",
    "\n",
    "print(\"\\nConditional Template Result (without profession):\")\n",
    "prompt = conditional_template.format(\n",
    "    name=\"Sam\",\n",
    "    age=\"22\",\n",
    "    profession=\"\"\n",
    ")\n",
    "print(get_completion(prompt))\n",
    "\n",
    "print(\"\\n\" + \"-\"*50 + \"\\n\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "List Template Result:\n",
      "Here are the categorized groups for the items you provided:\n",
      "\n",
      "### Fruits\n",
      "- Apple\n",
      "- Banana\n",
      "\n",
      "### Vegetables\n",
      "- Carrot\n",
      "\n",
      "### Tools\n",
      "- Hammer\n",
      "- Screwdriver\n",
      "- Pliers\n",
      "\n",
      "### Literature\n",
      "- Novel\n",
      "- Textbook\n",
      "- Magazine\n"
     ]
    }
   ],
   "source": [
    "# Template for list processing\n",
    "list_template = PromptTemplate(\n",
    "    template=\"Categorize these items into groups: {{ items }}. Provide the categories and the items in each category.\",\n",
    "    input_variables=[\"items\"]\n",
    ")\n",
    "\n",
    "# Using the list template\n",
    "print(\"List Template Result:\")\n",
    "prompt = list_template.format(\n",
    "    items=\"apple, banana, carrot, hammer, screwdriver, pliers, novel, textbook, magazine\"\n",
    ")\n",
    "print(get_completion(prompt))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Advanced Template Techniques\n",
    "\n",
    "Let's explore some more advanced techniques for working with prompt templates and variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Formatted List Template Result:\n",
      "The list of items you provided consists of programming languages, frameworks, and technologies commonly used in web development. Here's a summary and analysis of the items:\n",
      "\n",
      "### Summary of the List:\n",
      "1. **Programming Languages:**\n",
      "   - **Python**: A versatile, high-level programming language known for its readability and wide range of applications, including web development, data analysis, artificial intelligence, and more.\n",
      "   - **JavaScript**: A core web technology that enables interactive web pages and is essential for front-end development. It can also be used on the server side with environments like Node.js.\n",
      "\n",
      "2. **Markup and Styling Languages:**\n",
      "   - **HTML (HyperText Markup Language)**: The standard markup language for creating web pages. It structures the content on the web.\n",
      "   - **CSS (Cascading Style Sheets)**: A stylesheet language used for describing the presentation of a document written in HTML. It controls layout, colors, fonts, and overall visual aesthetics.\n",
      "\n",
      "3. **Frameworks and Libraries:**\n",
      "   - **React**: A JavaScript library for building user interfaces, particularly single-page applications. It allows developers to create reusable UI components.\n",
      "   - **Django**: A high-level Python web framework that encourages rapid development and clean, pragmatic design. It follows the \"batteries-included\" philosophy, providing many built-in features.\n",
      "   - **Flask**: A lightweight Python web framework that is easy to use and flexible, making it suitable for small to medium-sized applications.\n",
      "   - **Node.js**: A JavaScript runtime built on Chrome's V8 engine that allows developers to execute JavaScript on the server side. It is often used for building scalable network applications.\n",
      "\n",
      "### Patterns and Groupings:\n",
      "1. **Web Development Focus**: All items are related to web development, either as languages for building web applications (Python, JavaScript) or as technologies for structuring (HTML) and styling (CSS) web content.\n",
      "\n",
      "2. **Front-End vs. Back-End**:\n",
      "   - **Front-End Technologies**: JavaScript, HTML, CSS, and React are primarily used for client-side development, focusing on the user interface and user experience.\n",
      "   - **Back-End Technologies**: Python (with Django and Flask) and Node.js are used for server-side development, handling business logic, database interactions, and server management.\n",
      "\n",
      "3. **Language and Framework Relationships**:\n",
      "   - **Python Frameworks**: Django and Flask are both frameworks that utilize Python, showcasing its versatility in web development.\n",
      "   - **JavaScript Frameworks**: React is a library that enhances JavaScript's capabilities for building dynamic user interfaces, while Node.js extends JavaScript to server-side programming.\n",
      "\n",
      "4. **Full-Stack Development**: The combination of these technologies allows for full-stack development, where developers can work on both the front-end (React, HTML, CSS) and back-end (Django, Flask, Node.js) of web applications.\n",
      "\n",
      "### Conclusion:\n",
      "The list represents a comprehensive set of tools and languages essential for modern web development. Understanding the relationships and roles of these items can help developers choose the right technologies for their projects, whether they are focusing on front-end, back-end, or full-stack development.\n",
      "\n",
      "--------------------------------------------------\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Template with formatted list\n",
    "list_format_template = PromptTemplate(\n",
    "    template=\"Analyze the following list of items:\\n\"\n",
    "              \"{% for item in items.split(',') %}\"\n",
    "              \"- {{ item.strip() }}\\n\"\n",
    "              \"{% endfor %}\"\n",
    "              \"\\nProvide a summary of the list and suggest any patterns or groupings.\",\n",
    "    input_variables=[\"items\"]\n",
    ")\n",
    "\n",
    "\n",
    "# Using the formatted list template\n",
    "print(\"Formatted List Template Result:\")\n",
    "prompt = list_format_template.format(\n",
    "    items=\"Python, JavaScript, HTML, CSS, React, Django, Flask, Node.js\"\n",
    ")\n",
    "print(get_completion(prompt))\n",
    "\n",
    "print(\"\\n\" + \"-\"*50 + \"\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Dynamic Instruction Template Result:\n",
      "### Logo Design Concept for AI-Driven Healthcare Startup\n",
      "\n",
      "**1. Logo Elements:**\n",
      "   - **Symbol:** A stylized brain combined with a medical cross. The brain represents AI and intelligence, while the medical cross symbolizes healthcare. The two elements can be intertwined to show the integration of technology and health.\n",
      "   - **Typography:** Use a modern sans-serif font for the company name, ensuring it is clean and easy to read. The font should convey innovation and professionalism.\n",
      "\n",
      "**2. Color Palette:**\n",
      "   - **Primary Colors:** \n",
      "     - **Blue (#007BFF):** Represents trust, reliability, and technology.\n",
      "     - **Green (#28A745):** Symbolizes health, growth, and vitality.\n",
      "   - **Usage:** The brain can be in blue, while the medical cross can be in green. This color combination will create a harmonious and professional look.\n",
      "\n",
      "**3. Design Style:**\n",
      "   - **Simplicity:** The logo should be minimalistic, avoiding intricate details that may not be visible at smaller sizes. The shapes should be bold and clear.\n",
      "   - **Scalability:** Ensure that the logo maintains its integrity and recognizability when scaled down for use on business cards, websites, or app icons.\n",
      "\n",
      "**4. Layout:**\n",
      "   - **Horizontal Layout:** Place the symbol to the left of the company name for a balanced look. This layout is versatile for various applications, such as website headers and promotional materials.\n",
      "   - **Vertical Layout Option:** For social media profiles or app icons, a stacked version with the symbol above the company name can be created.\n",
      "\n",
      "**5. Mockup:**\n",
      "   - Create a mockup of the logo on various backgrounds (white, light gray, and dark) to ensure visibility and adaptability across different platforms.\n",
      "\n",
      "### Final Thoughts:\n",
      "This logo design concept effectively communicates the startup's focus on AI-driven healthcare solutions while adhering to the specified color constraints and ensuring simplicity for recognizability. The combination of the brain and medical cross symbolizes the innovative approach to healthcare, making it memorable and impactful.\n"
     ]
    }
   ],
   "source": [
    "# Template with dynamic instructions\n",
    "dynamic_instruction_template = PromptTemplate(\n",
    "    template=\"Task: {{ task }}\\n\"\n",
    "              \"Context: {{ context }}\\n\"\n",
    "              \"Constraints: {{ constraints }}\\n\\n\"\n",
    "              \"Please provide a solution that addresses the task, considers the context, and adheres to the constraints.\",\n",
    "    input_variables=[\"task\", \"context\", \"constraints\"]\n",
    ")\n",
    "\n",
    "# Using the dynamic instruction template\n",
    "print(\"Dynamic Instruction Template Result:\")\n",
    "prompt = dynamic_instruction_template.format(\n",
    "    task=\"Design a logo for a tech startup\",\n",
    "    context=\"The startup focuses on AI-driven healthcare solutions\",\n",
    "    constraints=\"Must use blue and green colors, and should be simple enough to be recognizable when small\"\n",
    ")\n",
    "print(get_completion(prompt))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
